using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Infrastructure.Data.Contexts;
using Microsoft.EntityFrameworkCore;

namespace UniversalAdmin.Infrastructure.Services
{
    public class JwtService
    {
        private readonly IConfiguration _config;
        private readonly ApplicationDbContext _db;

        public JwtService(IConfiguration config, ApplicationDbContext db)
        {
            _config = config;
            _db = db;
        }

        // 原方法保留，内部调新重载，默认 2 小时
        public string GenerateToken(User user)
            => GenerateToken(user, rememberMe: false);

        // 新重载：根据 rememberMe 决定过期时间
        /// <summary>
        /// 生成JWT Token - 性能优化版本
        /// </summary>
        /// <param name="user">用户对象，包含Id、Username、Email等信息</param>
        /// <param name="rememberMe">是否记住用户（延长Token有效期）</param>
        /// <returns>生成的JWT Token字符串</returns>
        public string GenerateToken(User user, bool rememberMe)
        {
            // 根据rememberMe设置Token有效期：7天（记住我）或2小时（临时会话）
            var expires = rememberMe
                ? DateTime.UtcNow.AddDays(7)
                : DateTime.UtcNow.AddHours(2);

            // 缓存密钥对象以避免重复创建
            var key = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));

            // 创建签名凭证（使用HmacSha256算法）
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            // 定义Token中的用户声明（Claims） - 减少不必要的声明
            var claims = new[]
            {
                new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), // 用户唯一标识
                new Claim(ClaimTypes.Name, user.Username)                  // 用户名
                // 移除Email声明以减少token大小和生成时间
            };

            // 生成JWT Token
            var token = new JwtSecurityToken(
                issuer: _config["Jwt:Issuer"],     // 发行者
                audience: _config["Jwt:Audience"], // 受众
                claims: claims,                     // 用户声明
                expires: expires,                  // 过期时间
                signingCredentials: creds);        // 签名凭证

            // 将Token序列化为字符串并返回
            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        /// <summary>
        /// 验证并解析 JWT Token
        /// </summary>
        public ClaimsPrincipal? ValidateToken(string token)
        {
            var handler = new JwtSecurityTokenHandler();
            var key = Encoding.UTF8.GetBytes(_config["Jwt:Key"]!);

            try
            {
                return handler.ValidateToken(token, new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ClockSkew = TimeSpan.Zero
                }, out _);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 异步验证Token（检查黑名单）
        /// </summary>
        public async Task<ClaimsPrincipal?> ValidateTokenAsync(string token)
        {
            // 首先检查token是否在黑名单中
            var isBlacklisted = await _db.TokenBlacklist
                .AnyAsync(t => t.Token == token && t.ExpireAt > DateTime.UtcNow);

            if (isBlacklisted)
            {
                return null; // token已被拉黑
            }

            // 如果不在黑名单中，进行常规验证
            return ValidateToken(token);
        }
    }
}